<script setup lang="ts">
import {BoxGeometry, Group, Mesh, MeshBasicMaterial, RepeatWrapping, Vector3} from "three";
import {useSeek, useTexture, useTresContext} from "@tresjs/core";

import {ThemeModelMeta, ThemeVO} from "@/api/pb/theme";
import * as ConfigApi from '@/api/infra/config'

import {DefaultWallMaterialConfigKey, WallType} from "@/types/web3d";
import {useLoaderStorage} from "@/store/modules/web3d/loader";

const { scene } =  useTresContext()
const { seekByName } = useSeek()

const loader = useLoaderStorage()

// 默认网格大小
const gridSideLength = inject<number>('gridSideLength')!

// 主题数据
const theme = inject<Ref<ThemeVO>>('theme')!
// 实际大小，长 宽 高
// 2D和3D不同，length -> w，width -> h
const length = gridSideLength * theme.value.grid.w
const width = gridSideLength * theme.value.grid.h
const height = gridSideLength * 0.5

/** 获取默认配置 */
// 默认纹理
const defaultTexture = ref({
  bottom: '',
  side: '',
  top: ''
})
const getDefaultConfig = async () => {
  const datas = await Promise.all([
    // 地面材质
    ConfigApi.getConfigKey(DefaultWallMaterialConfigKey.BOTTOM),
    // 侧面材质
    ConfigApi.getConfigKey(DefaultWallMaterialConfigKey.SIDE),
    // 顶部材质
    ConfigApi.getConfigKey(DefaultWallMaterialConfigKey.TOP),
  ])

  defaultTexture.value.bottom = datas[0]
  defaultTexture.value.side = datas[1]
  defaultTexture.value.top = datas[2]

  // TODO 这里不能赋值，否则会改变原本数据，导致不准确
  // if(!theme.value.modelMeta) {
  //   theme.value.modelMeta = {} as unknown as ThemeModelMeta
  // }
  // const modelMeta = theme.value.modelMeta
  //
  // if(!modelMeta.wallsMaterial) {
  //   modelMeta.wallsMaterial = {} as unknown as { [key in WallType]: string }
  // }
  // const wallsMaterial = modelMeta.wallsMaterial
  //
  // // 初始化默认的墙体材质
  // wallsMaterial.bottom = wallsMaterial.bottom || datas[0]
  // wallsMaterial.left = wallsMaterial.left || datas[1]
  // wallsMaterial.right = wallsMaterial.right || datas[1]
  // wallsMaterial.front = wallsMaterial.front || datas[1]
  // wallsMaterial.back = wallsMaterial.back || datas[1]
  // wallsMaterial.top = wallsMaterial.top || datas[2]

}

/** 初始化墙体 */
// 墙体 Group
const wallGroup = inject<Group>('wallGroup')!

// 墙面厚度
const thickness = gridSideLength / 16
// 默认墙体配置
const defaultWallConfigs = [
  // 底部
  {
    name: 'bottom',
    position: new Vector3(0, 0 - thickness / 2, 0),
    size: {width: length, height: thickness, depth: width,}
  },
  // 顶部
  {
    name: 'top',
    position: new Vector3(0, height + thickness / 2, 0),
    size: {width: length, height: thickness, depth: width,}
  },
  // 左侧
  {
    name: 'left',
    position: new Vector3(-length / 2 + thickness / 2, height / 2, 0),
    size: {width: thickness, height: height, depth: width,}
  },
  // 右侧
  {
    name: 'right',
    position: new Vector3(length / 2 - thickness / 2, height / 2, 0),
    size: {width: thickness, height: height, depth: width,}
  },
  // 前方
  {
    name: 'front',
    position: new Vector3(0, height / 2, width / 2 - thickness / 2),
    size: {width: length, height: height, depth: thickness,}
  },
  // 后方
  {
    name: 'back',
    position: new Vector3(0, height / 2, -width / 2 + thickness / 2),
    size: {width: length, height: height, depth: thickness,}
  },
];

// 初始化墙面并添加至场景
const initWall = async () => {
  for (const config of defaultWallConfigs) {
    const {name, position, size} = config
    // 这里有问题，texture 应该是是一个数组，但是如果只有一个参数的话 texture 为单个 Texture 对象
    let materialUrl = theme.value.modelMeta?.wallsMaterial?.[name]
    if (!materialUrl) {
      if (name === 'bottom') {
        materialUrl = defaultTexture.value.bottom
      } else if (name === 'top') {
        materialUrl = defaultTexture.value.top
      } else {
        materialUrl = defaultTexture.value.side
      }
    }

    const texture = await useTexture([materialUrl])
    texture.wrapS = RepeatWrapping
    texture.wrapT = RepeatWrapping
    texture.repeat.set(length, width)

    const wall = new Mesh(
      new BoxGeometry(size.width, size.height, size.depth),
      new MeshBasicMaterial({map: texture})
    );
    wall.name = name
    wall.position.copy(position);
    wallGroup.add(wall);
  }

  // 暂时隐藏顶部
  const topWall = seekByName(wallGroup, 'top') as Mesh
  topWall.visible = false

  scene.value.add(wallGroup)
}

/** 统一顺序执行 */
await loader.loader([
  // 加载墙体
  getDefaultConfig,
  initWall,
])

</script>

<template>
  <div></div>
</template>

<style scoped lang="scss">

</style>
